package g

import (
	"context"
	"encoding/base64"
	"encoding/hex"
	"errors"
	"fmt"
	"gitee.com/injoyai/goutil/chans"
	"gitee.com/injoyai/goutil/conv"
	"gitee.com/injoyai/goutil/crypt/des"
	"gitee.com/injoyai/goutil/crypt/md5"
	"gitee.com/injoyai/goutil/maps/wait"
	"gitee.com/injoyai/goutil/oss"
	uuid "github.com/satori/go.uuid"
	"log"
	"net/http"
	_ "net/http/pprof"
	"runtime/debug"
	"time"
)

// Input 监听用户输入
func Input(hint ...interface{}) string { return oss.Input(hint...) }

// WithCancel context.WithCancel
func WithCancel(ctx ...context.Context) {
	var c context.Context
	if len(ctx) > 0 && ctx[0] != nil {
		c = ctx[0]
	} else {
		c = context.Background()
	}
	context.WithCancel(c)
}

// Count 遍历
// @num,数量,-1为死循环
// @interval,间隔
func Count(num int, interval ...time.Duration) <-chan int { return chans.Count(num, interval...) }

// Interval 间隔触发
func Interval(interval time.Duration, nums ...int) <-chan int {
	num := conv.GetDefaultInt(-1, nums...)
	return chans.Count(num, interval)
}

// Encrypt 字符串加密,DES加密,ECB模式,非标长度不足会补
func Encrypt(str string, keys ...string) string {
	key := conv.GetDefaultString("injoy.ai", keys...)
	return des.EncryptECB(str, key)
}

// Decrypt 字符串解密,DES加密,ECB模式,非标长度不足会补
func Decrypt(str string, keys ...string) string {
	key := conv.GetDefaultString("injoy.ai", keys...)
	return des.DecryptECB(str, key)
}

// MD5 加密,32位小写
func MD5(s string) string { return md5.Encrypt(s) }

// Pprof 性能剖析
// _ "net/http/pprof"
// go tool pprof http://localhost:6060/debug/pprof/heap
// go tool pprof http://localhost:6060/debug/pprof/profile?seconds=60
func Pprof(port int) {
	go func() {
		log.Println(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
	}()
}

// UUID uuid
func UUID() string { return uuid.NewV4().String() }

// Recover 错误捕捉
func Recover(err *error, stack ...bool) {
	if er := recover(); er != nil {
		if err != nil {
			if len(stack) > 0 && stack[0] {
				*err = errors.New(fmt.Sprintln(er) + string(debug.Stack()))
			} else {
				*err = errors.New(fmt.Sprintln(er))
			}
		}
	}
}

// RecoverFunc 错误捕捉并执行函数
func RecoverFunc(fn func(err interface{})) { fn(recover()) }

// Try 尝试运行,捕捉错误
func Try(fn func() error) (err error) {
	defer Recover(&err)
	return fn()
}

// TryCatch 其他语言的try catch
func TryCatch(fn func() error, catch ...func(err error)) {
	if err := Try(fn); err != nil {
		for _, v := range catch {
			v(err)
		}
	}
}

// Retry 重试,默认3次
func Retry(fn func() error, nums ...int) (err error) {
	num := conv.GetDefaultInt(3, nums...)
	for i := 0; i < num; i++ {
		if err = Try(fn); err == nil {
			return
		}
	}
	return
}

// PanicErr 如果是错误则panic
func PanicErr(err error) {
	if err != nil {
		panic(err)
	}
}

// Panic 配合Recover使用
func Panic(v interface{}) { panic(v) }

// ListenExit 监听退出信号
func ListenExit(handler ...func()) { oss.ListenExit(handler...) }

// Wait 等待
func Wait(key string) (interface{}, error) { return wait.Wait(key) }

// Done 结束等待
func Done(key string, value interface{}) { wait.Done(key, value) }

// DecodeHEX hex.DecodeString
func DecodeHEX(s string) ([]byte, error) { return hex.DecodeString(s) }

// EncodeHEX hex.EncodeToString
func EncodeHEX(bs []byte) string { return hex.EncodeToString(bs) }

// DecodeBase64 base64.StdEncoding.DecodeString
func DecodeBase64(s string) ([]byte, error) { return base64.StdEncoding.DecodeString(s) }

// EncodeBase64 base64.StdEncoding.EncodeToString
func EncodeBase64(bs []byte) string { return base64.StdEncoding.EncodeToString(bs) }
